module factor_update #(
    parameter reg [7:0] HEAD_BYTE = 8'haa
) (
    input sys_clk,
    input rst_n,
    input uart_rdy_i,
    input [7:0] uart_rx_data_i,
    output reg uart_rdy_clr_o,
    output reg [31:0] div_factor_o
);

  localparam reg [2:0] IDLE = 3'h0;
  localparam reg [2:0] BYTE3 = 3'h1;
  localparam reg [2:0] BYTE2 = 3'h2;
  localparam reg [2:0] BYTE1 = 3'h3;
  localparam reg [2:0] BYTE0 = 3'h4;

  reg [2:0] r_state;
  reg [2:0] state_next;
  reg [23:0] r_factor;
  reg uart_rdy_d;
  wire uart_rdy_rising;

  always @(posedge sys_clk, negedge rst_n) begin
    if (~rst_n) begin
      uart_rdy_d <= 1'b0;
    end else begin
      uart_rdy_d <= uart_rdy_i;
    end
  end
  assign uart_rdy_rising = uart_rdy_i & ~(uart_rdy_d);

  wire head_cmp;

  assign head_cmp = (uart_rx_data_i == HEAD_BYTE);

  always @(posedge sys_clk, negedge rst_n) begin
    if (~rst_n) begin
      uart_rdy_clr_o <= 1'b0;
    end else if (uart_rdy_rising) begin
      uart_rdy_clr_o <= 1'b1;
    end else begin
      uart_rdy_clr_o <= 1'b0;
    end
  end

  always @(*) begin
    case (r_state)
      IDLE:
      if (head_cmp) begin
        state_next = BYTE3;
      end else begin
        state_next = r_state;
      end
      BYTE3:   state_next = BYTE2;
      BYTE2:   state_next = BYTE1;
      BYTE1:   state_next = BYTE0;
      BYTE0:   state_next = IDLE;
      default: state_next = IDLE;
    endcase
  end

  always @(posedge sys_clk, negedge rst_n) begin
    if (~rst_n) begin
      r_state <= IDLE;
    end else if (uart_rdy_rising) begin
      r_state <= state_next;
    end
  end

  always @(posedge sys_clk, negedge rst_n) begin
    if (~rst_n) begin
      r_factor <= 24'h0;
      div_factor_o <= 32'h0;
    end else if (uart_rdy_rising) begin
      case (r_state)
        BYTE3: r_factor[23:16] <= uart_rx_data_i;
        BYTE2: r_factor[15:8] <= uart_rx_data_i;
        BYTE1: r_factor[7:0] <= uart_rx_data_i;
        BYTE0: begin
          div_factor_o <= {r_factor[23:0], uart_rx_data_i};
        end
      endcase
    end
  end

endmodule
